package nc.bs.bcsi.convert.translate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import nc.bs.framework.common.NCLocator;
import nc.config.bcsi.ContextLoader;
import nc.impl.pubapp.pattern.database.DataAccessUtils;
import nc.itf.bcsi.convert.translate.IAttrTranslator;
import nc.itf.bcsi.convert.translate.TransParam;
import nc.itf.org.IGroupQryService;
import nc.pub.bcsi.BillDefAttrUtil;
import nc.vo.bcsi.entity.AggBcsiRuleVO;
import nc.vo.bcsi.entity.BaseVO;
import nc.vo.bcsi.entity.BcsiRuleBVO;
import nc.vo.bcsi.enumeration.EContextKey;
import nc.vo.bcsi.enumeration.Eparam;
import nc.vo.bcsi.enumeration.EsendType;
import nc.vo.bcsi.util.MdRefMetaNameUtil;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.org.GroupVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.IAttributeMeta;
import nc.vo.pub.IVOMeta;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pubapp.pattern.data.IRowSet;
import nc.vo.pubapp.pattern.model.meta.entity.vo.VOMetaFactory;
import nc.vo.pubapp.pattern.pub.SqlBuilder;

import org.apache.commons.lang.StringUtils;

public class GeneralAttrTranslator implements IAttrTranslator {
	public static final String FIELD_SEND_DEFAULT_SEL = "code";

	public Map<String, Object> constructAsSrcVal(Set<String> vals) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (String val : vals) {
			map.put(val, val);
		}
		return map;
	}

	public Map<String, Object> getTranslateInfoMap(String pkOrg,
			String sendfield, Set<String> vals, TransParam param,
			IVOMeta metadata, Integer sendType) throws BusinessException {
		if (UFBoolean.FALSE.equals(isNeedTranslate(sendfield))) {
			return constructAsSrcVal(vals);
		}

		String refDocName = getRefDocName(metadata, sendfield);
		String refTableName = MdRefMetaNameUtil.getInstance().getRefMetaName(
				refDocName);

		IVOMeta refMeta = VOMetaFactory.getInstance().getVOMeta(refTableName);
		String tableName = refMeta.getPrimaryAttribute().getColumn().getTable()
				.getName();

		String pk_field = refMeta.getPrimaryAttribute().getName();

		String selectfield = BillDefAttrUtil.getSelColName(sendfield);
		if (selectfield == null) {
			selectfield = "code";
		}

		if (tableName.toUpperCase().endsWith("ORG")) {
			param.setParams(new String[] { "pk_group" });
		}

		String sql = null;
		if (EsendType.SEND.toInteger().equals(sendType)) {
			sql = conSqlSend(pkOrg, tableName, pk_field, selectfield, vals,
					param);
		} else {
			sql = conSqlReceive(pkOrg, tableName, pk_field, selectfield, vals,
					param);
		}

		return queryRefDocInfo(sql);
	}

	public void translateSingleField(String pkOrg, AggBcsiRuleVO billDef,
			BcsiRuleBVO item, List<BaseVO> baseVOs, IVOMeta metadata,
			Integer sendType) throws BusinessException {
		Map<String, Object> translateInfoMap = getTranslateInfoMap(pkOrg, item,
				baseVOs, metadata, sendType);

		udpateVO(item, baseVOs, translateInfoMap, sendType);
	}

	private String conSqlReceive(String pkOrg, String tableName,
			String pk_field, String selectfield, Set<String> vals,
			TransParam param) throws BusinessException {
		SqlBuilder sql = new SqlBuilder();
		sql.append("SELECT ");
		sql.append(tableName + "." + selectfield);
		sql.append(" , ");
		sql.append(pk_field);
		sql.append(" FROM ");
		sql.append(tableName + " " + tableName);
		sql.append(" WHERE ");
		sql.append(tableName + "." + selectfield, (String[]) vals.toArray(new String[vals.size()]));

		sql.append(getRegionWherePart(pkOrg, tableName, param));
		sql.append(" AND DR=0 ");
		return sql.toString();
	}

	private String conSqlSend(String pkOrg, String tableName, String pk_field,
			String selectfield, Set<String> vals, TransParam param)
			throws BusinessException {
		SqlBuilder sql = new SqlBuilder();
		sql.append("SELECT ");
		sql.append(tableName + "." + pk_field);
		sql.append(" , ");
		sql.append(tableName + "." + selectfield);
		sql.append(" FROM ");
		sql.append(tableName + " " + tableName);
		sql.append(" WHERE ");
		sql.append(tableName + "." + pk_field,
				(String[]) vals.toArray(new String[vals.size()]));

		sql.append(getRegionWherePart(pkOrg, tableName, param));

		return sql.toString();
	}

	private String getRefDocName(IVOMeta metadata, String sendfield) {
		IAttributeMeta attribute = metadata.getAttribute(BillDefAttrUtil
				.getRealSendField(sendfield));

		String referenceDoc = attribute.getReferenceDoc();
		return referenceDoc;
	}

	private String getRegionWherePart(String pkOrg, String tableName,
			TransParam param) throws BusinessException {
		if ((param == null) || (param.getParams() == null)
				|| (param.getParams().length == 0)) {
			return "";
		}
		String paramStr = param.getParams()[0];
		SqlBuilder sql = new SqlBuilder();

		String groupCode = ContextLoader.getInstance().getContext(
				EContextKey.group_code.name());

		GroupVO[] groupVOs = ((IGroupQryService) NCLocator.getInstance()
				.lookup(IGroupQryService.class))
				.queryAllGroupVOSByCodeS(new String[] { groupCode });

		if ((groupVOs == null) || (groupVOs.length == 0)) {
			throw new BusinessException(NCLangRes4VoTransl.getNCLangRes()
					.getStrByID("401750_0", "0401750-0011")
					+ groupCode
					+ NCLangRes4VoTransl.getNCLangRes().getStrByID("401750_0",
							"0401750-0012"));
		}

		String pk_group = groupVOs[0].getPk_group();

		if (Eparam.PK_GROUP.value().equals(paramStr)) {
			sql.append(" and (" + tableName + ".pk_group", pk_group);
			sql.append(" or " + tableName + ".pk_group = '~') ");
		} else if (Eparam.PK_ORG.value().equals(paramStr)) {
			sql.append(" and (" + tableName + ".pk_group", pk_group);
			sql.append(" or " + tableName + ".pk_group = '~') ");
			sql.append(" and " + tableName + ".pk_org", pkOrg);
		}
		return sql.toString();
	}

	private Map<String, Object> getTranslateInfoMap(String pkOrg,
			BcsiRuleBVO item, List<BaseVO> baseVOs, IVOMeta metadata,
			Integer sendType) throws BusinessException {
		String sendfield = item.getVsendfiled();
		String dest = item.getVdest();
		String transparam = item.getVparam();

		Set<String> vals = new HashSet<>();
		for (BaseVO baseVO : baseVOs) {
			String val;
			if (EsendType.RECEIVE.toInteger().equals(sendType)) {
				val = (String) baseVO.getAttributeValue(BillDefAttrUtil
						.getRealSendField(sendfield));

			} else {
				val = (String) baseVO.getAttributeValue(dest);
			}
			if (StringUtils.isNotEmpty(val)) {
				vals.add(val);
			}
		}
		if (vals.size() == 0) {
			return null;
		}
		Map<String, Object> translateInfoMap = null;
		try {
			TransParam param = new TransParam();
			param.setParams(transparam);
			translateInfoMap = getTranslateInfoMap(pkOrg, sendfield, vals,
					param, metadata, sendType);

		} catch (Exception e) {
			throw new BusinessException(e.getMessage());
		}
		return translateInfoMap;
	}

	private Map<String, Object> queryRefDocInfo(String sql) {
		DataAccessUtils utils = new DataAccessUtils();
		IRowSet rowset = utils.query(sql);
		if (rowset.size() == 0) {
			return null;
		}
		Map<String, Object> map = new HashMap<>();
		String[][] rows = rowset.toTwoDimensionStringArray();
		for (int i = 0; i < rows.length; i++) {
			map.put(rows[i][0], rows[i][1]);
		}
		return map;
	}

	private void udpateVO(BcsiRuleBVO item, List<BaseVO> baseVOs,
			Map<String, Object> translateInfoMap, Integer sendType)
			throws BusinessException {
		if ((translateInfoMap == null) || (translateInfoMap.size() == 0)) {
			return;
		}
		String dest = (String) item.getAttributeValue("vdest");
		if (EsendType.RECEIVE.toInteger().equals(sendType)) {
			dest = BillDefAttrUtil.getRealSendField((String) item
					.getAttributeValue("vsendfiled"));
		}

		List<String> errCodeList = new ArrayList<>();
		for (BaseVO baseVO : baseVOs) {
			String val = (String) baseVO.getAttributeValue(dest);
			if (StringUtils.isNotEmpty(val)) {

				Object translatedVal = translateInfoMap.get(val);
				if (translatedVal == null) {
					errCodeList.add((String) translatedVal);
				} else {
					baseVO.setAttributeValue(dest, translatedVal);
				}
			}
		}
		if (errCodeList.size() > 0) {
			String errMsg = NCLangRes4VoTransl.getNCLangRes().getStrByID(
					"401750_0", "0401750-0013")
					+ item.getAttributeValue("vsendfiled")
					+ NCLangRes4VoTransl.getNCLangRes().getStrByID("401750_0",
							"0401750-0014")
					+ errCodeList.toArray(new String[errCodeList.size()]);

			throw new BusinessException(errMsg);
		}
	}

	protected UFBoolean isNeedTranslate(String sendfield) {
		return UFBoolean.TRUE;
	}
}